﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Management;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Timers;
using WMPLib;
using System.Configuration;
using MusicRipperDataAccess;
using JewelCaseWriter;

namespace UWSP_Music_Ripper
{
    public partial class Form1 : Form
    {
		#region Fields (7) 

//        Album myAlbum;
//        AlbumHandler myAlbumHandler;
//        CD_Reader.CD_Reader myCD;
 //       System.Timers.Timer myTimer;
        // WqlEventQuery q;
       // ManagementScope scope;
       // ManagementEventWatcher w = null;
        RipperApi api = null;

		#endregion Fields 

		#region Constructors (1) 

        public Form1()
        {
            InitializeComponent();
            this.api = new RipperApi();
            api.registerTimerCallback(UpdateRipStatus);
            api.registerRipDoneCallback(UpdateWhenDone);   
            ListCdDrives();
            if (lstDrives.Items.Count > 0)
            {
                string s = lstDrives.Items[0].ToString().Substring(0,1);
                api.MyCD = new CD_Reader.CD_Reader(s);
            }
            this.lblSource.Text = ConfigurationManager.AppSettings["source"];
            api.SourceDir = this.lblSource.Text;
            this.lblDestination.Text = ConfigurationManager.AppSettings["destination"];
            api.DestinationDir = this.lblDestination.Text;
            StartMonitoringCD();
           
        }

		#endregion Constructors 

		#region Delegates and Events (2) 

		// Delegates (2) 

        delegate void GetCdInfoCallBack(CD_Reader.CD_Reader myCD);
        delegate void UpdateRipStatusCallBack(string inValue);

		#endregion Delegates and Events 

		#region Methods (20) 

		// Protected Methods (1) 

        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
        protected override void Dispose(bool disposing)
        {
            api.Dispose();
           
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }
		// Private Methods (19) 

        private void btnDrives_Click(object sender, EventArgs e)
        {
            System.IO.DriveInfo[] drives = System.IO.DriveInfo.GetDrives();
            List<string> myDrives = new List<string>();
            foreach (System.IO.DriveInfo drive in drives)
            {
                myDrives.Add(drive.Name + "  |  " + drive.DriveType.ToString());
            }
            this.lstTracks.DataSource = myDrives;
        }

        private void btnListTracks_Click(object sender, System.EventArgs e)
        {
            SetInfoFromCD(api.MyCD);
        }

        private void btnPrint_Click(object sender, EventArgs e)
        {
            this.PrintJewelCase();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            List<string> titles = api.GetAlbumTitles();
            StringBuilder sb = new StringBuilder();
            foreach (string title in titles)
            {
                sb.Append(title + System.Environment.NewLine);
            }

            MessageBox.Show(sb.ToString());

        //    List<string> attributes = myCD.ListAllAttributes();

        }

        private void chooseSourceDirToolStripMenuItem_Click(object sender, EventArgs e)
        {
            FolderBrowserDialog fbd = new FolderBrowserDialog();
            if (fbd.ShowDialog() == DialogResult.OK)
            {
                this.lblSource.Text = fbd.SelectedPath;
                Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
                config.AppSettings.Settings["source"].Value = fbd.SelectedPath;
                config.Save(ConfigurationSaveMode.Modified);
            }
        }

        private void destinationDirectoryToolStripMenuItem_Click(object sender, EventArgs e)
        {
            FolderBrowserDialog fbd = new FolderBrowserDialog();
            if (fbd.ShowDialog() == DialogResult.OK)
            {
                this.lblDestination.Text = fbd.SelectedPath;
            }
        }

        private void SetInfoFromCD(CD_Reader.CD_Reader myCD)
        {
            //todo refactor reference to CD_Reader
           if (this.lstTracks.InvokeRequired)
           {
              GetCdInfoCallBack del = new GetCdInfoCallBack( SetInfoFromCD );
              this.Invoke( del, new object[0] );
           }
           else
           {
              string title = myCD.GetCD_Title( );
              string artist = myCD.GetArtist( );
             
              if (! api.DoesThisAlbumExist( title, artist ))
              {
                 this.lstTracks.DataSource = myCD.GetTracks( );
                 this.lblCD_Title.Text = title;
                 this.lblArtist.Text = artist;
              }
              else
              {
                 MessageBox.Show( title + " by " + artist + " already exists in the collection." );
                 api.MyAlbum = null;
              }
           }
        }

        private List<string> GetTracksToRip()
        {          
            List<string> TracksToRip = new List<string>();
            foreach (object i in lstTracks.CheckedItems)
            {
                TracksToRip.Add(i.ToString());
            }
            return TracksToRip;
        }

        private void ListCdDrives()
        {

            System.IO.DriveInfo[] drives = System.IO.DriveInfo.GetDrives();
            List<string> myDrives = new List<string>();
            foreach (System.IO.DriveInfo drive in drives)
            {
                if (drive.DriveType == System.IO.DriveType.CDRom)
                    myDrives.Add(drive.Name);
            }
            lstDrives.DataSource = myDrives;
        }

        private void lnkAll_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            for (int i = 0; i < lstTracks.Items.Count; i++ )
            {
                this.lstTracks.SetItemChecked(i, true);
            }
        }

        private void lstDrives_SelectedIndexChanged(object sender, EventArgs e)
        {
            string s = lstDrives.SelectedItem.ToString().Substring(0, 1);
            api.MyCD = new CD_Reader.CD_Reader(s);
        }


        private void PrintJewelCase()
        {
            JewelCaseHelper jch = new JewelCaseHelper();
            
            //jch.WriteTheCase(myData);

        }

        private bool ReadyToRip()
        {
            bool ready = false;
            if (this.lblSource.Text.Equals("Source Directory", StringComparison.CurrentCultureIgnoreCase))
            {
                MessageBox.Show("You need to set the source directory to the same directory you windows Media Player rips to.");
            }
            else if (this.lblDestination.Text.Equals("Destination Directory", StringComparison.CurrentCultureIgnoreCase))
            {
                MessageBox.Show("You need to set the destination directory to where you want the new files to be copied.");
            }
            else if (! api.MyCD.isCD_Ready())
            {
                MessageBox.Show("There is not a cd loaded yet");
            }
            else if (lstTracks.CheckedItems.Count == 0)
            {
                MessageBox.Show("Pleae select some tracks to rip and rename");
            }
            else
            {
                ready = true;
            }
            return ready;
        }

        private void RipTracks(object sender, EventArgs e)
        {
            if (ReadyToRip())
            {
                List<string> TracksToRip = this.GetTracksToRip();
                api.rip(TracksToRip);
            }
        }



        private void StartMonitoringCD()
        {
            api.StartMonitoringCD(updateUiWithCdInfo);
        }

        private void UpdateRipStatus(string inStatus)
        {
            if (this.lblRipStatus.InvokeRequired)
            {
                UpdateRipStatusCallBack del = new UpdateRipStatusCallBack(UpdateRipStatus);
                this.Invoke(del, new object[1] { inStatus });
            }
            else
            {
                this.lblRipStatus.Text = inStatus + "% done ripping this cd";
            }
        }

        private void updateUiWithCdInfo(object sender, EventArrivedEventArgs e)
        {
          
            //Get the Event object and display it
            PropertyData pd;
            if ((pd = e.NewEvent.Properties["TargetInstance"]) != null)
            {
              
                ManagementBaseObject mbo = pd.Value as ManagementBaseObject;
                // if CD removed VolumeName == null
                if (mbo.Properties["VolumeName"].Value != null)
                {
                   //todo refactor to remove reference to api.myCD
                    this.SetInfoFromCD(api.MyCD);
                }
                   
            }
        }
        private void UpdateWhenDone(String s)
        {
            MessageBox.Show(s);
        }

		#endregion Methods 
    }
}
